package view;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;
import javax.swing.JComboBox;
import java.awt.FlowLayout;
import java.awt.GridBagLayout;
import java.awt.Checkbox;

/**
 * The Class ViewPhotoGUI - displays photos.
 * @author Dmitry
 */
public class ViewPhotoGUI extends AbstractGUI {
	
	/** The "Delete" button. */
	private JButton btnDelete = null;
	
	/** The img icon. */
	private ImageIcon imgIcon = null;
	
	/** The image. */
	BufferedImage image = null;
	
	/** The "Plus" button. */
	private JButton btnPlus = null;
	
	/** The "Minus" button. */
	private JButton btnMinus =  null;
	
	/** The ScrollPane */
	private JScrollPane scrollPane = null;
	
	/** Zoom in/out label */
	private JLabel lblZoomInout;
	
	/** The panel which holds the photo */
	private MapScale test = null;
	
	/** The combo box which contains user's layers */
	private JComboBox comboBox = null;
	
	/** The button which returns the image to its original size*/
	private JButton btnResetPhoto = null;
	
	/** The button which starts animation*/
	private JButton btnPlay = null;
	
	/** The panel which holds the buttons at the bottom of the JFrame*/
	private JPanel BottomPanel = null;
	
	/** The panel which holds the buttons at the right of the JFrame*/
	private JPanel rightPanel = null;
	
	/** This is a a "Stop" button.*/
	private JButton btnStop = null;
	
	/** This is a "Next" button.*/
	private JButton btnNext = null;
	
	/** This is a "Previous" button.*/
	private JButton btnPrev = null;
	private JButton btnUpdatePhotoLayers;
	private JButton btnDropLayers = null;
	private JLabel lblLocation = null;
	private JLabel lblShowlocation = null;
	private JLabel lblTimestamp = null;
	private JLabel lblShowTimeStamp = null;
	
	/**
	 * Instantiates a new view photo gui.
	 *
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	public ViewPhotoGUI() {
		getContentPane().setLayout(null);
		getBottomPanel().add(getBtnPlus());
		getBottomPanel().add(getBtnMinus());
		getBottomPanel().add(getResetButton());
		getBottomPanel().add(getBackButton());
		getContentPane().add(getPanel());
		getContentPane().add(getLblZoomInout());
		getContentPane().add(getBottomPanel());
		getContentPane().add(getRightPanel());
		getContentPane().add(getLblLocation());
		getContentPane().add(getLblShowLocation());
		getContentPane().add(getLblTimestamp());
		getContentPane().add(getLblShowTimeStamp());
		
		
		this.setTitle("View Photo");
		this.setBounds(100, 100, 938, 616);
		this.setVisible(true);
		this.setResizable(false);
		this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		
//		getPanelRight().add(getBtnAddLayer(), "2, 2");
	}

	/**
	 * This method both creates and returns "Reset size" button instance.
	 * @return JButton instance.
	 */
	private JButton getResetButton(){
		if(btnResetPhoto == null){
			btnResetPhoto = new JButton("Reset size");
			btnResetPhoto.setBounds(715, 349, 103, 23);
		}
		return btnResetPhoto;
	}
	
	/**
	 * This method adds combo box to the window.
	 */
	public void addLayerCustomerButtonToWindow()
	{
		getRightPanel().add(getComboBox());
		getRightPanel().add(getBtnDropLayers());
	}
	
	/**
	 * This method adds "Delete" button to the window.
	 */
	public void addArchiveButtonsToWindow(){
		getRightPanel().add(getBtnDelete());
		getRightPanel().add(getBtnUpdatePhotoLayers());
	}
	
	/**
	 * This method both creates and returns JScrollPane instance.
	 * @return JScrollPane instance.
	 */
	private JScrollPane getPanel(){
		if(scrollPane == null){
			test = new MapScale();
			scrollPane = new JScrollPane(test);
			scrollPane.setBounds(20, 11, 721, 477);
		}
		return scrollPane;
	}
	
	/**
	 * This method both creates and returns panel at the bottom.
	 * @return JPanel instance.
	 */
	private JPanel getBottomPanel() {
		if (BottomPanel == null) {
			BottomPanel = new JPanel();
			BottomPanel.setBounds(104, 538, 443, 34);
			BottomPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
		}
		return BottomPanel;
	}
	//#################################################################################
	
	public void setComboBoxContent(String name){
		getComboBox().addItem(name);
	}
	
	private JLabel getLblLocation(){
		if(lblLocation == null){
			lblLocation = new JLabel("Location: ");
			lblLocation.setBounds(279, 499, 58, 14);
		}
		return lblLocation;
	}
	
	private JLabel getLblShowLocation(){
		if(lblShowlocation == null){
			lblShowlocation = new JLabel("");
			lblShowlocation.setBounds(346, 499, 64, 14);
		}
		return lblShowlocation;
	}
	
	private JLabel getLblTimestamp(){
		if(lblTimestamp == null){
			lblTimestamp = new JLabel("TimeStamp:");
			lblTimestamp.setBounds(20, 499, 75, 14);
		}
		return lblTimestamp;
	}
	
	private JLabel getLblShowTimeStamp(){
		if(lblShowTimeStamp == null){
			lblShowTimeStamp = new JLabel("");
			lblShowTimeStamp.setBounds(104, 499, 161, 14);
		}
		return lblShowTimeStamp;
	}
	
	
	private JButton getBtnDropLayers(){
		if(btnDropLayers == null){
			btnDropLayers = new JButton("Drop Layers");
			btnDropLayers.setBounds(751, 373, 171, 23);
		}
		return btnDropLayers;
	}
	
	private JPanel getRightPanel() {
		if (rightPanel == null) {
			rightPanel = new JPanel();
			rightPanel.setBounds(751, 11, 171, 338);
			rightPanel.setLayout(new GridLayout(10,1,1,4));
		}
		return rightPanel;
	}
	
	private JButton getBtnPlay() {
		if (btnPlay == null) {
			btnPlay = new JButton("Play");
		}
		return btnPlay;
	}
	
	private JButton getBtnStop() {
		if (btnStop == null) {
			btnStop = new JButton("Stop");
		}
		return btnStop;
	}
	
	public void setAnimationButtons(){
		
		getRightPanel().add(getBtnPlay());
		getRightPanel().add(getBtnStop());
		getRightPanel().add(getBtnNext());
		getRightPanel().add(getBtnPrev());
	}
	
	private JButton getBtnNext() {
		if (btnNext == null) {
			btnNext = new JButton(">>");
		}
		return btnNext;
	}
	
	private JButton getBtnPrev() {
		if (btnPrev == null) {
			btnPrev = new JButton("<<");
		}
		return btnPrev;
	}
	
	private JButton getBtnUpdatePhotoLayers() {
		if (btnUpdatePhotoLayers == null) {
			btnUpdatePhotoLayers = new JButton("Update Photo Layers");
			btnUpdatePhotoLayers.setBounds(764, 379, 107, 34);
		}
		return btnUpdatePhotoLayers;
	}
	
	public void setLblShowLocation(int location){
		getLblShowLocation().setText(Integer.toString(location));
	}
	
	public void setLblShowTimeStamp(String timeStamp){
		getLblShowTimeStamp().setText(timeStamp);
	}
	
	//#################################################################################
	
	/**
	 * This class both creates and returns combo box instance.
	 * @return JComboBox instance.
	 */
	private JComboBox getComboBox(){
		if(comboBox == null){
			comboBox = new JComboBox();
		}
		return comboBox;
	}
	
	
	/**
	 * This method both creates and returns a "Plus" button instance.
	 * @return JButton "Plus" button.
	 */
	private JButton getBtnPlus(){
		if(btnPlus == null){
			btnPlus = new JButton("+");
			btnPlus.setBounds(715, 417, 44, 23);
		}
		return btnPlus;
	}
	
	/**
	 * This method both creates and returns a "Minus" button instance.
	 * @return JButton "Minus" button.
	 */
	private JButton getBtnMinus(){
		if(btnMinus == null){
			btnMinus = new JButton("-");
			btnMinus.setBounds(715, 383, 44, 23);
		}
		return btnMinus;
	}
	
	/**
	 * Gets the "Detele" button.
	 * @return delete button instance.
	 */
	private JButton getBtnDelete(){
		if(btnDelete == null){
			btnDelete = new JButton("Delete");
		}
		return btnDelete;
	}
	
	/**
	 * Gets the back button.
	 *
	 * @return back button instance.
	 */
	private JButton getBackButton(){
		if(backButton == null){
			backButton = new JButton("Back");
			backButton.setBounds(350, 459, 89, 23);
		}
		return backButton;
	}
	
	/**
	 * This class displays the photo on the window.
	 */
	public void displayImage(){
		test.setImage(getImage());
	}
	
	public String getComboBoxSelectedItem(){
		return getComboBox().getSelectedItem().toString();
	}
	
	/**
	 * This method sets the image into the image icon. 
	 * @param image is a BufferedImage - which the GUI will show.
	 */
	public void setImage(BufferedImage image){
		this.image = image;
	}
	
	/**
	 * This method adds an action listener to the "Delete" button.
	 * @param listener
	 */
	public void addDeleteButtonListener(ActionListener listener){
		getBtnDelete().addActionListener(listener);
	}
	
	/**
	 * This method adds an action listener to the "Plus" button.
	 * @param listener
	 */
	public void addPlusButtonListener(ActionListener listener){
		getBtnPlus().addActionListener(listener);
	}
	
	/**
	 * This method adds an action listener to the "Minus" button.
	 * @param listener
	 */
	public void addMinusButtonListener(ActionListener listener){
		getBtnMinus().addActionListener(listener);
	}
	
	/**
	 * This method adds an action listener to the "Drop Layers" button.
	 * @param listener
	 */
	public void addDropLayersButtonListener(ActionListener listener){
		getBtnDropLayers().addActionListener(listener);
	}
	
	/**
	 * This method adds an action listener to the "Reset size" button.
	 * @param listener
	 */
	public void addResetButtonActionListener(ActionListener listener){
		getResetButton().addActionListener(listener);
	}
	
	/**
	 * This method adds an action listener to the "Play/Stop" button.
	 * @param listener
	 */
	public void addPlayButtonActionListener(ActionListener listener){
		getBtnPlay().addActionListener(listener);
	}
	
	/**
	 * This method adds an action listener to the "Play/Stop" button.
	 * @param listener
	 */
	public void addStopButtonActionListener(ActionListener listener){
		getBtnStop().addActionListener(listener);
	}
	
	/**
	 * This method adds an action listener to the "Next" button.
	 * @param listener
	 */
	public void addNextButtonActionListener(ActionListener listener){
		getBtnNext().addActionListener(listener);
	}
	
	/**
	 * This method adds an action listener to the "Prev" button.
	 * @param listener
	 */
	public void addPrevButtonActionListener(ActionListener listener){
		getBtnPrev().addActionListener(listener);
	}
	
	/**
	 * This method adds an action listener to the "Update Photo Layer" button.
	 * @param listener
	 */
	public void addUpdateLayerButtonListener(ActionListener listener){
		getBtnUpdatePhotoLayers().addActionListener(listener);
	}
	
	/**
	 * This method adds an action listener to the combo box.
	 * @param listener
	 */
	public void addComboBoxListener(ActionListener listener){
		getComboBox().addActionListener(listener);
	}
	
	/**
	 * This Getter returns panel's Height.
	 * @return panel's height.
	 */
	public int getPanelHeight()
	{
		return getPanel().getHeight()-3;
	}
	
	/**
	 * This Getter returns panel's Width.
	 * @return panel's width.
	 */
	public int getPanelWidth(){
		return getPanel().getWidth()-3;
	}
	
	/**
	 * This method both creates and creates a "Zoom In/Out" label.
	 * @return JLabel instance.
	 */
	private JLabel getLblZoomInout() {
		if (lblZoomInout == null) {
			lblZoomInout = new JLabel("Zoom In/Out:");
			lblZoomInout.setBounds(20, 547, 82, 14);
		}
		return lblZoomInout;
	}
	
	/**
	 * This method returns BufferedImage instance.
	 * @return
	 */
	public BufferedImage getImage(){
		return image;
	}
	
	
	/**
	 * This method makes zoom in.
	 */
	public void zoomIn(){
		test.zoomIn();
	}
	
	/**
	 * This method makes zoom out.
	 */
	public void zoomOut(){
		test.zoomOut();
	}
	
	/**
	 * This method resets image's side to its original size.
	 */
	public void resetPhotoSize(){
		test.resetPhotoSize();
	}
	
	public void displayNothing(){
		test.displayNothing();
	}
	
	/**
	 * This method shows a confirmation message when archive worker wants to delete a image.
	 * @return
	 */
	public boolean showWarningMessage(){
		int response = JOptionPane.showConfirmDialog(null, "Are you sure you want to delete this image?", "Are You Sure?",
		        JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
		    if (response == JOptionPane.YES_OPTION)
		    	return true;
		    return false;
	}
	
	public void showMessage(String msg){
		JOptionPane.showMessageDialog(this, msg);
	}
	
	
	/**
	 * This method simulates "Back" button click.
	 */
	public void clickBackButton(){
		getBackButton().doClick();
	}
	
	
	/**
	 * This class shows the photo.
	 * JScrollPane contains this JPanel.
	 * This class zooms in to and out of the photo.
	 * @author Dmitry
	 *
	 */
	 class MapScale extends JPanel {
	    BufferedImage image = null;
	    double scale = 1.0;
	    double plusZoom = 1.0;
	    double minusZoom = 1.0;
	    
	    public MapScale(){
	    	
	    }
	    

		public void setImage(BufferedImage im){
	    	this.image = im;
	    }
	    
	    public MapScale(BufferedImage image) {
	        this.image = image;
	    }
	 
	    protected void paintComponent(Graphics g) {
	    	if(image == null)
	    		return;
	        super.paintComponent(g);
	        Graphics2D g2 = (Graphics2D)g;
	        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
	                            RenderingHints.VALUE_INTERPOLATION_BICUBIC);
	        double x = (getWidth() - scale*image.getWidth())/2;
	        double y = (getHeight() - scale*image.getHeight())/2;
	        AffineTransform at = AffineTransform.getTranslateInstance(x,y);
	        at.scale(scale, scale);
	        g2.drawRenderedImage(image, at);
	    }
	 
	    public Dimension getPreferredSize() {
	    	if(image == null)
	    		return new Dimension(6,6);
	        int w = (int)(scale*image.getWidth());
	        int h = (int)(scale*image.getHeight());
	        return new Dimension(w, h);
	    }
	 
	    public void zoomIn(){
	    	plusZoom = plusZoom + 0.1;
	    	minusZoom = minusZoom + 0.1;
	    	reSize(plusZoom);
	    }
	    
	    public void zoomOut(){
	    	if(minusZoom == 1.0)
	    		return;
	    	minusZoom = minusZoom - 0.1;
	    	plusZoom = plusZoom - 0.1;
	    	reSize(minusZoom);
	    }
	    
	    public void resetPhotoSize() {
	    	plusZoom = 1.0;
	    	minusZoom = 1.0;
	    	reSize(plusZoom);
	    }
	    
	    public void displayNothing() {
	    	plusZoom = 0;
	    	minusZoom = 0;
	    	reSize(plusZoom);
	    }
	    
	    public void reSize(double value){
	       scale = (value+4)/5.0;
	       revalidate();
	       repaint();
	    }
	   
	   
	}
}
